package com.kischang.blog.service;

import com.kischang.blog.dao.ReviewDao;
import com.kischang.blog.dao.TopicDao;
import com.kischang.blog.model.PageInfo;
import com.kischang.blog.model.Reply;
import com.kischang.blog.model.Topic;
import com.kischang.blog.model.User;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.IRStatistics;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.eval.RecommenderIRStatsEvaluator;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.eval.AverageAbsoluteDifferenceRecommenderEvaluator;
import org.apache.mahout.cf.taste.impl.eval.GenericRecommenderIRStatsEvaluator;
import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Component
public class TopicService {
    public final static int RECOMMENDER_NUM = 3;
    public static final int RECOMMENDER_SIZE = 5;

    @Autowired
	private TopicDao dao;
	@Autowired
	private ReviewDao reviewDao;

	@Transactional(readOnly=true)
	public List<Topic> getTopicByPage(PageInfo pageInfo){
		pageInfo.setTotalPage(dao.getTopicCount());
		return dao.getTopicByPage(pageInfo);
	}
	@Transactional(readOnly=true)
	public List<Topic> getTopicByPageAndMenu(int mid,PageInfo pageInfo){
		pageInfo.setTotalPage(dao.getTopicCountByMenu(mid));
		return dao.getTopicByPageAndMenu(mid, pageInfo);
	}
	
	@Transactional
	public Topic getTopicByID(int tid) {
        return getTopicByID(tid,false,null);
    }
	@Transactional
	public Topic getTopicByID(int tid, boolean add, User user) {
		return dao.getTopicByID(tid,add,user);
	}
	
	@Transactional(readOnly=true)
	public List<Reply> getReviewByPageAndTopicID(int tid, PageInfo pageInfo) {
		pageInfo.setTotalPage(reviewDao.getReviewCountByTid(tid));
		return reviewDao.getReviewByPageAndTopicID(tid,pageInfo);
	}
	
	@Transactional
	public void save(Topic topic){
		dao.save(topic);
	}
	@Transactional
	public void update(Topic topic) {
		dao.update(topic);
	}

    @Transactional
    public List<Topic> getRecommend(int tId){
        List<Topic> topicList = new ArrayList<Topic>();
        try{
            MysqlDataSource mysqlDataSource = new MysqlDataSource();
            mysqlDataSource.setURL("jdbc:mysql://localhost:3306/blog?user=root&password=root");
            DataModel model= new MySQLJDBCDataModel(mysqlDataSource,"browsehistory","uid","tid","val","time");
            final ItemSimilarity itemSimilarity = new EuclideanDistanceSimilarity(model);
            RecommenderBuilder recommenderBuilder = new RecommenderBuilder() {
                @Override
                public Recommender buildRecommender(DataModel model) throws TasteException {
                    return new GenericItemBasedRecommender(model, itemSimilarity);
                }
            };

            new AverageAbsoluteDifferenceRecommenderEvaluator().evaluate(recommenderBuilder, null, model, 0.7, 1.0);
            RecommenderIRStatsEvaluator evaluator = new GenericRecommenderIRStatsEvaluator();
            IRStatistics stats = evaluator.evaluate(recommenderBuilder, null, model, null, 2, GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 1.0);
            System.out.printf("Recommender IR Evaluator: [Precision:%s,Recall:%s]\n", stats.getPrecision(), stats.getRecall());

            LongPrimitiveIterator iter = model.getUserIDs();
            List<Long> recItems = new ArrayList<Long>();
            while (iter.hasNext()) {
                long uid = iter.nextLong();
                System.out.printf("uid:%s,", uid);
                List<RecommendedItem> list = recommenderBuilder.buildRecommender(model).recommend(uid, RECOMMENDER_NUM);
                if (list.size() > 0) {
                    for (RecommendedItem recommendation : list) {
                        System.out.printf("(%s,%f)", recommendation.getItemID(), recommendation.getValue());
                        if(recItems.size() >= RECOMMENDER_SIZE){
                            break;
                        }else{
                            recItems.add(recommendation.getItemID());
                        }
                    }
                }
            }
            //开始取推荐栏目
            for (int i = 0; i < RECOMMENDER_SIZE; i++) {
                if(recItems.size() <= i){
                    break;
                }
                Topic topic = dao.getTopicByID(recItems.get(i).intValue(),false,null);
                if(topic != null){
                    topicList.add(topic);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return topicList;
    }
}
